/**
 * 
 */
package taskman.xml;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import taskman.Constants;
import taskman.Task;
import taskman.User;
// import taskman.Interface3;
import taskman.Interface4;


public class XmlHelper {
	
	private static SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
	
	//How to use: Call this function and it returns all tasks from the main task file, no arguments needed
	public static List<Task> loadAllTasks() {
		List<Task> tasks = new ArrayList<Task>();
		
		Document taskDocument = parseXmlFile(Constants.RESOURCE_FOLDER + Constants.TASKS_FILE);
		
		//Gets root xml element
		Element rootTasks = taskDocument.getDocumentElement();
		
		//Gets list of every task
		NodeList allTasks = rootTasks.getElementsByTagName("task");
		
		if(allTasks != null && allTasks.getLength() > 0) {
			for(int i = 0 ; i < allTasks.getLength();i++) {

				//get the task element
				Element el = (Element)allTasks.item(i);

				//get the Task object
				Task t = getTask(el);

				//add it to list
				tasks.add(t);
			}
		}
		
		return tasks;
	}
	
	public static List<User> loadAllUsers() {
		List<User> users = new ArrayList<User>();
		
		Document userDocument = parseXmlFile(Constants.RESOURCE_FOLDER + "users.xml");
		
		//Gets root xml element
		Element rootTasks = userDocument.getDocumentElement();
		
		//Gets list of every task
		NodeList allUsers = rootTasks.getElementsByTagName("user");
		
		if(allUsers != null && allUsers.getLength() > 0) {
			for(int i = 0 ; i < allUsers.getLength();i++) {

				//get the user element
				Element el = (Element)allUsers.item(i);

				//get the user object
				User u = getUser(el);

				//add it to list
				users.add(u);
			}
		}
		
		return users;
	}
	
	public static List<Interface4> loadAllInterface4() {
		List<Interface4> interface4 = new ArrayList<Interface4>();
		
		Document Interface4Document = parseXmlFile(Constants.RESOURCE_FOLDER + "interface.xml");
		
		//Gets root xml element
		Element rootTasks = Interface4Document.getDocumentElement();
		
		//Gets list of every task
		NodeList allInterface4 = rootTasks.getElementsByTagName("interface");
		
		if(allInterface4 != null && allInterface4.getLength() > 0) {
			for(int i = 0 ; i < allInterface4.getLength();i++) {

				//get the user element
				Element el = (Element)allInterface4.item(i);

				//get the user object
				Interface4 w = getInterface4(el);

				//add it to list
				interface4.add(w);
			}
		}
		
		return interface4;
	}
	
	private static Document parseXmlFile(String filename){
		//get the factory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

		try {

			//Using factory get an instance of document builder
			DocumentBuilder db = dbf.newDocumentBuilder();

			//parse using builder to get DOM representation of the XML file
			Document dom = db.parse(filename);

			return dom;
		}catch(ParserConfigurationException pce) {
			pce.printStackTrace();
		}catch(SAXException se) {
			se.printStackTrace();
		}catch(IOException ioe) {
			ioe.printStackTrace();
		}
		return null;
	}
	
	private static Task getTask(Element e) {
		Task t = new Task();
		t.setId(getStringValue(e, "id"));
		t.setPersonId(getStringValue(e, "personId"));
		t.setTitle(getStringValue(e, "title"));
		t.setDeadline(getDateValue(e, "deadline"));
		t.setDeliverable(getStringValue(e, "deliverable"));
		t.setDescription(getStringValue(e, "description"));
		t.setDuration(getDoubleValue(e, "duration"));
		t.setParentTaskId(getStringValue(e, "parentTaskId"));
		t.setStartDate(getDateValue(e, "startDate"));
		t.setPercentageComplete(getIntValue(e, "percentComplete"));
		t.setNumberOfDaysElapsed(getIntValue(e, "numberOfDaysElapsed"));
		return t;
	}
	
	private static User getUser(Element e) {
		User u = new User();
		u.setName(getStringValue(e, "name"));
		u.setId(getStringValue(e, "id"));
		u.setHours(getStringValue(e, "hours"));
		u.setTasks(getStringValue(e, "tasks"));
		return u;
	}
	
	private static Interface4 getInterface4(Element e) {
		Interface4 w = new Interface4();
		w.setName(getStringValue(e, "name"));
		w.setId(getStringValue(e, "id"));
		w.setHours(getStringValue(e, "hours"));
		w.setTasks(getStringValue(e, "tasks"));
		w.setmanager(getStringValue(e, "manager"));
		w.setstarted(getStringValue(e, "started"));
		return w;
	}
	
	private static String getStringValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
	
	private static double getDoubleValue(Element ele, String tagName) {
		return Double.parseDouble(getStringValue(ele, tagName));
	}
	
	private static int getIntValue(Element ele, String tagName) {
		return Integer.parseInt(getStringValue(ele, tagName));
	}
	
	private static Date getDateValue(Element ele, String tagName){
		
		Date dateVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			try
			{
				dateVal = dateFormat.parse(el.getFirstChild().getNodeValue());
			}
			catch (ParseException e) {
				e.printStackTrace();
			}
		}

		return dateVal;
	}
	
	public static void saveUsersToFile(List<User> users) {
		try {
			FileWriter fw = new FileWriter(Constants.RESOURCE_FOLDER + Constants.USERS_FILE,false);
			BufferedWriter writer = new BufferedWriter(fw);
			writer.write("<users>\n");
			for(User u : users) {
				writer.write(createXmlUser(u));
			}
			writer.write("</users>\n");
			writer.close();
		}
		catch(IOException e) {
			System.out.println("FATAL ERROR: Failed to create / load users.xml");
			System.out.println("FATAL ERROR: " + e.getMessage());
		}
		
		
	}
	
	public static void saveInterface4ToFile(List<Interface4> Interface4) {
		try {
			FileWriter fw = new FileWriter(Constants.RESOURCE_FOLDER + Constants.INTERFACE_FILE,false);
			BufferedWriter writer = new BufferedWriter(fw);
			writer.write("<interfaces>\n");
			for(Interface4 w : Interface4) {
				writer.write(createXmlInterface4(w));
			}
			writer.write("</interfaces>\n");
			writer.close();
		}
		catch(IOException e) {
			System.out.println("FATAL ERROR: Failed to create / load interface.xml");
			System.out.println("FATAL ERROR: " + e.getMessage());
		}
		
		
	}
	
	public static void saveTasksToFile(List<Task> tasks) {
		saveTasksToFile(tasks, Constants.TASKS_FILE);
	}
	
	public static void saveTasksToFile(List<Task> tasks, String filename) {
		try {
			FileWriter fw = new FileWriter(Constants.RESOURCE_FOLDER + filename,false);
			BufferedWriter writer = new BufferedWriter(fw);
			writer.write("<tasks>\n");
			for(Task t : tasks) {
				writer.write(createXmlTask(t));
			}
			writer.write("</tasks>\n");
			writer.close();
		}
		catch(IOException e) {
			System.out.println("FATAL ERROR: Failed to create / load " + Constants.TASKS_FILE);
			System.out.println("FATAL ERROR: " + e.getMessage());
		}
	}
	
	private static String createXmlUser(User u) {
		StringBuilder builder = new StringBuilder();
		builder.append("<user>\n");
		builder.append("<id>").append(u.getId()).append("</id>\n");
		builder.append("<name>").append(u.getName()).append("</name>\n");
		builder.append("<hours>").append(u.getHours()).append("</hours>\n");
		builder.append("<tasks>").append(u.getTasks()).append("</tasks>\n");
		builder.append("</user>\n");
			
		return builder.toString();
	}
	
	private static String createXmlInterface4(Interface4 w) {
		StringBuilder builder = new StringBuilder();
		builder.append("<interface>\n");
		builder.append("<id>").append(w.getId()).append("</id>\n");
		builder.append("<name>").append(w.getName()).append("</name>\n");
		builder.append("<hours>").append(w.getHours()).append("</hours>\n");
		builder.append("<tasks>").append(w.getTasks()).append("</tasks>\n");
		builder.append("<manager>").append(w.getmanager()).append("</manager>\n");
		builder.append("<started>").append(w.getstarted()).append("</started>\n");
		builder.append("</interface>\n");
			
		return builder.toString();
	}
	
	public static String createXmlTask(Task t) {
		StringBuilder builder = new StringBuilder();
		builder.append("<task>\n");
		builder.append("<id>").append(t.getId()).append("</id>\n");
		builder.append("<deadline>").append(dateFormat.format(t.getDeadline())).append("</deadline>\n");
		builder.append("<deliverable>").append(t.getDeliverable()).append("</deliverable>\n");
		builder.append("<description>").append(t.getDescription()).append("</description>\n");
		builder.append("<duration>").append(t.getDuration()).append("</duration>\n");
		builder.append("<personId>").append(t.getPersonId()).append("</personId>\n");
		builder.append("<title>").append(t.getTitle()).append("</title>\n");
		builder.append("<parentTaskId>").append(t.getParentTaskId()==null? "" : t.getParentTaskId()).append("</parentTaskId>\n");
		builder.append("<percentComplete>").append(t.getPercentageComplete()).append("</percentComplete>\n");
		builder.append("<numberOfDaysElapsed>").append(t.getNumberOfDaysElapsed()).append("</numberOfDaysElapsed>\n");
		builder.append("<startDate>").append(dateFormat.format(t.getStartDate())).append("</startDate>\n");
		builder.append("</task>\n");

		return builder.toString();
	}

}
